package com.itsm.example.audit.impl;

import com.itsm.example.audit.pojo.context.AuditContext;
import com.itsm.example.statemachine.bo.ItsmContext;
import com.itsm.example.statemachine.bo.ItsmEvent;
import com.itsm.example.statemachine.bo.ItsmState;
import com.itsm.example.statemachine.factory.StateMachineStrategy;
import com.itsm.example.audit.pojo.enums.StateMachineEnum;
import com.itsm.example.audit.pojo.event.AuditEvent;
import com.itsm.example.audit.pojo.state.AuditState;
import com.itsm.statemachine.Action;
import com.itsm.statemachine.Condition;
import com.itsm.statemachine.StateMachine;
import com.itsm.statemachine.builder.StateMachineBuilder;
import com.itsm.statemachine.builder.StateMachineBuilderFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author benym
 * @date 2023/7/12 17:24
 */
@Component
public class AuditMachine implements StateMachineStrategy {

    @Resource
    @Qualifier("passOrRejectAction")
    private Action<ItsmState, ItsmEvent, ItsmContext> passOrRejectAction;

    @Resource
    @Qualifier("doneAction")
    private Action<ItsmState, ItsmEvent, ItsmContext> doneAction;

    @Resource
    @Qualifier("asyncDoneAction")
    private Action<ItsmState, ItsmEvent, ItsmContext> asyncDoneAction;
    @Resource
    @Qualifier("passOrRejectCondition")
    private Condition<ItsmContext> passOrRejectCondition;

    @Resource
    @Qualifier("doneCondition")
    private Condition<ItsmContext> doneCondition;

    @Override
    public String getMachineType() {
        return StateMachineEnum.TEST_MACHINE.getCode();
    }

    /**
     * | From(开始状态) | To(抵达状态) | Event(事件) | When(条件)            | Perform(执行动作)  |
     * | -------------- | ------------ | ----------- | --------------------- | ------------------ |
     * | 已申请      | 爸爸同意 | 审核通过    | passOrRejectCondition | passOrRejectAction |
     * | 爸爸同意    | 妈妈同意 | 审核通过    | passOrRejectCondition | passOrRejectAction |
     * | 已申请     | 爸爸不同意 | 审核驳回    | passOrRejectCondition | passOrRejectAction |
     * | 爸爸同意   | 妈妈不同意 | 审核驳回    | passOrRejectCondition | passOrRejectAction |
     * | 已申请    | 已完成状态    | 已完成        | doneCondition        | doneAction        |
     * | 爸爸同意  | 已完成状态    | 已完成        | doneCondition        | doneAction        |
     * | 妈妈同意  | 已完成状态    | 已完成        | doneCondition        | doneAction        |
     *
     * @return StateMachine stateMachine
     */
//    @Bean
    public StateMachine<ItsmState, ItsmEvent, ItsmContext> stateMachine() {
        StateMachineBuilder<ItsmState, ItsmEvent, ItsmContext> builder = StateMachineBuilderFactory.create();
        //提交申请
        builder.internalTransition().within(AuditState.APPLY)
                .on(AuditEvent.NEW)
                .when(passOrRejectCondition)
                .asyncPerform(asyncDoneAction)
                .perform(passOrRejectAction);
        // 已申请->爸爸同意
        builder.externalTransition().from(AuditState.APPLY).to(AuditState.DAD_PASS)
                .on(AuditEvent.PASS)
                .when(passOrRejectCondition)
                .perform(passOrRejectAction);
        // 已申请->爸爸不同意
        builder.externalTransition().from(AuditState.APPLY).to(AuditState.DAD_REJ)
                .on(AuditEvent.REJECT)
                .when(passOrRejectCondition)
                .perform(passOrRejectAction);
        // 爸爸同意->妈妈同意
        builder.externalTransition().from(AuditState.DAD_PASS).to(AuditState.MOM_PASS)
                .on(AuditEvent.PASS)
                .when(passOrRejectCondition)
                .perform(passOrRejectAction);
        // 爸爸同意->妈妈不同意
        builder.externalTransition().from(AuditState.DAD_PASS).to(AuditState.MOM_REJ)
                .on(AuditEvent.REJECT)
                .when(passOrRejectCondition)
                .perform(passOrRejectAction);

        // 爸爸不同意->已完成
        builder.externalTransition().from(AuditState.DAD_REJ).to(AuditState.DONE)
                .on(AuditEvent.DONE)
                .when(doneCondition)
                .perform(doneAction);
        // 妈妈不同意->已完成
        builder.externalTransition().from(AuditState.MOM_REJ).to(AuditState.DONE)
                .on(AuditEvent.DONE)
                .when(doneCondition)
                .perform(doneAction);
        // 已申请->已完成
        // 爸爸同意->已完成
        // 妈妈同意->已完成
        builder.externalTransitions().fromAmong(AuditState.APPLY, AuditState.DAD_PASS, AuditState.MOM_PASS)
                .to(AuditState.DONE)
                .on(AuditEvent.DONE)
                .when(doneCondition)
                .asyncPerform(asyncDoneAction)
                .perform(doneAction);
        // 设置线程池
        builder.setThreadPoolExecutor(new ThreadPoolExecutor(
                Runtime.getRuntime().availableProcessors() * 2, // corePoolSize
                Runtime.getRuntime().availableProcessors() * 4, // maximumPoolSize
                60L, // keepAliveTime
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>() // workQueue
        ));
        return builder.build(getMachineType());
    }
}
